package com.example.rpc.registry.zookeeper;

import com.example.rpc.common.util.CollectionUtil;
import com.example.rpc.registry.ServiceDiscovery;

import org.I0Itec.zkclient.ZkClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

/**
 * 基于ZooKeeper的服务发现接口实现
 * @Author Anita
 * @Date 2017/12/25 17:56
 */
public class ZooKeeperServiceDiscovery implements ServiceDiscovery {

    private Logger LOGGER = LoggerFactory.getLogger(ZooKeeperServiceDiscovery.class);
    private String zkAddress;

    public ZooKeeperServiceDiscovery(String zkAddress){
        this.zkAddress = zkAddress;
    }

    @Override
    public String discover(String name){
        ZkClient zkClient = new ZkClient(zkAddress,Constant.ZK_SESSION_TIMEOUT,Constant.ZK_CONNECTION_TIMEOUT);
        LOGGER.debug("connect zookeeper");
        try{
            //获取service节点
            String servicePath = Constant.ZK_REGISTRY_PATH+"/"+name;
            if(!zkClient.exists(servicePath)){
                throw new RuntimeException(String.format("can not find any service node on path: %s", servicePath));
            }
            List<String> addressList = zkClient.getChildren(servicePath);
            if(CollectionUtil.isEmpty(addressList)){
                throw new RuntimeException(String.format("can not find any address node on path: %s", servicePath));
            }
            //获取address节点
            // 路径/registry/HelloService-version2/address- data: 127.0.0.1:3000
            // address已经是service文件夹下的address- 那一层了
            String address;
            int size = addressList.size();
            if(size == 1){
                //若只有一个地址，则获取该地址
                address = addressList.get(0);
                LOGGER.debug("get only address node: {}", address);
            } else {
                address = addressList.get(ThreadLocalRandom.current().nextInt(size));
                LOGGER.debug("get random address node: {}", address);
            }
            //获取address节点的值
            String addressPath = servicePath+"/"+address;
            return zkClient.readData(addressPath);
        } finally {
            zkClient.close();
        }

    }
}
